﻿

namespace NCP.Recruiting.Repository.SqlServer.UnitOfWork {
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Data.Entity.ModelConfiguration.Conventions;
    using System.Linq;
    using NCP.Recruiting.Repository.SqlServer.Data;
    using NCP.Recruiting.Repository.SqlServer.UnitOfWork.Mapping;

    public class MainBCUnitOfWork
         : DbContext, IQueryableUnitOfWork {

        #region IQueryableUnitOfWork Members

        public DbSet<TEntity> CreateSet<TEntity>()
            where TEntity : class {
            return base.Set<TEntity>();
        }

        public void Attach<TEntity>(TEntity item)
            where TEntity : class {
            //attach and set as unchanged
            base.Entry<TEntity>(item).State = EntityState.Unchanged;
        }

        public void SetModified<TEntity>(TEntity item)
            where TEntity : class {
            //this operation also attach item in object state manager
            base.Entry<TEntity>(item).State = EntityState.Modified;
        }
        public void ApplyCurrentValues<TEntity>(TEntity original, TEntity current)
            where TEntity : class {
            //if it is not attached, attach original and set current values
            base.Entry<TEntity>(original).CurrentValues.SetValues(current);
        }

        public void Commit() {
            base.SaveChanges();
        }

        public void CommitAndRefreshChanges() {
            bool saveFailed = false;

            do {
                try {
                    base.SaveChanges();

                    saveFailed = false;

                }
                catch (DbUpdateConcurrencyException ex) {
                    saveFailed = true;

                    ex.Entries.ToList()
                              .ForEach(entry => {
                                  entry.OriginalValues.SetValues(entry.GetDatabaseValues());
                              });

                }
            } while (saveFailed);

        }

        public void RollbackChanges() {
            // set all entities in change tracker 
            // as 'unchanged state'
            base.ChangeTracker.Entries()
                              .ToList()
                              .ForEach(entry => entry.State = EntityState.Unchanged);
        }

        public IEnumerable<TEntity> ExecuteQuery<TEntity>(string sqlQuery, params object[] parameters) {
            return base.Database.SqlQuery<TEntity>(sqlQuery, parameters);
        }

        public int ExecuteCommand(string sqlCommand, params object[] parameters) {
            return base.Database.ExecuteSqlCommand(sqlCommand, parameters);
        }

        #endregion

        #region DbContext Overrides

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
            //Remove unused conventions
            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

            //Add entity configurations in a structured way using 'TypeConfiguration’ classes

            // Company
            modelBuilder.Configurations.Add(new CompanyEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new ContractEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new DepartmentEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new DealEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new MessageTemplateEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new PhotoEntityTypeConfiguration());

            // job position
            modelBuilder.Configurations.Add(new JobpositionEntityTypeConfiguration());

            // Candiate 
            modelBuilder.Configurations.Add(new CandidateEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new TagEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new InterviewEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new ReceiptEntityTypeConfiguration());

            // Reume
            modelBuilder.Configurations.Add(new ResumeEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new EducationEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new WorkEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new SkillEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new TrainingEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new CertificationEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new SavedSearchEntityTypeConfiguration());
            modelBuilder.Configurations.Add(new BookmarkEntityTypeConfiguration());

            //
            modelBuilder.Configurations.Add(new ShortMessageEntityTypeConfiguration());
        }
        #endregion
    }
}
